package scfg.utils;

import java.util.*;
import java.io.*;

import scfg.output.Display;
import scfg.output.RNAFormattedFile;
import desposito6.utils.*;

public class StructureAggregator {

	public static String ORIG = "ct", REP = "rna_formatted";
	private static Display output;

	static {
		output = new Display("StructureAggregator");
	}

	public static RNAFormattedFile convertCtFile(File f,
			RNAFormattedFile rnaFile) {
		if (!f.exists()) {
			output.eout("File does not exist");
			return null;
		}
		if (!f.getAbsolutePath().replace("\n", "").endsWith("nopct")) {
			output.eout("Invalid Filename");
			return null;
		}
		try {
//			output.out("\tConverting...");
			Scanner scan = new Scanner(f);
			String line = scan.nextLine();
			if (line.contains("html"))
				return null;
			String[] arr = line.split("\\s+");
			if (!arr[1].equals("1")) {
				scan.nextLine();
				scan.nextLine();
				scan.nextLine();
				scan.nextLine();
			}
			StringBuilder structure = new StringBuilder();
			StringBuilder sequence = new StringBuilder();
			recurseOnBP(scan, sequence, structure);
			rnaFile.put("seq", sequence.toString());
			rnaFile.put("nat", structure.toString());
			return rnaFile;
		} catch (Exception e) {
			output.eout(f.getAbsolutePath());
			output.eoutST(e);
		}
		return null;
	}

	public static void recurseOnBP(Scanner scan,
			StringBuilder sequence, StringBuilder structure) {
		while (scan.hasNext()) {
			String line = scan.nextLine().trim();
			String[] arr = line.split("\\s+");
			int count = Integer.parseInt(arr[0]);
			sequence.append(arr[1]);
			if (arr[4].equals("0"))
				structure.append(".");
			else {
				Integer i = Integer.parseInt(arr[4]);
				if (count < i)
					structure.append("(");
				else
					structure.append(")");
			}
			count++;
		}
	}

	public static boolean processFile(File f, String destinationDir) {
		if (!f.getAbsolutePath().matches(".*nopct$")) {
			String newName = f.getAbsolutePath().replaceAll("nopct\n", "nopct");
			f.renameTo(new File(newName));
			f = new File(newName);
		}
		output.out("\tProcessing " + f.getName().replaceAll("\n", "") + "...");
		RNAFormattedFile rnaFile = convertCtFile(f, new RNAFormattedFile(
				destinationDir + f.getName().replaceAll("\n", "") + ".rna"));
		if (rnaFile != null) {
			rnaFile.writeToFile(false);
			output.out("\tDone...");
			return true;
		}
		System.err.println("\tFile not processed:" + f.getAbsolutePath());
		if (f.getAbsolutePath().replace("\n", "").endsWith("nopct"))
			f.renameTo(new File(f.getAbsolutePath() + ".error"));
		return false;
	}

	public static boolean processDir(File base, String destinationDir) {
		File dir = new File(destinationDir);
		if (!base.exists()) {
			output.eout("Base Directory directory does not extist:\n\t"
					+ base.getAbsolutePath());
			return false;
		}
		if (!dir.exists() && dir.mkdir()) {
			output.out("Created directory: " + dir.getAbsolutePath());
		}
		File[] files = base.listFiles();
		boolean added = false;
		if (!destinationDir.endsWith("/"))
			destinationDir += "/";
		output.out("\nProcessing" + base.getAbsolutePath() + "\nWriting to "
				+ destinationDir + "\n");
		for (File f : files) {
			if (f.isDirectory())
				processDir(f, destinationDir + f.getName());
			else
				added = processFile(f, destinationDir) || added;
		}
		return added;
	}

	public static void compressFiles(File dir, String dest) {
		if (!dir.exists())
			return;
		try {
			BufferedWriter bf = new BufferedWriter(new FileWriter(dest));
			File[] files = dir.listFiles();
			output.out("Writing files to " + dest);
			Scanner scan;
			for (File f : files) {
				if (f.getName().endsWith(".rna")) {
					System.out.println("processing " + f.getName());
					scan = new Scanner(f);
					bf.write(f.getName().replace(".rna", ""));
					bf.write("\n");
					bf.write(scan.nextLine());
					bf.write("\n");
					bf.write(scan.nextLine());
					bf.write("\n");
					scan.close();
				}
			}
			bf.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String helpMessage() {
		return "\n[scfg.utils.StructureAggregator]\n\t"
				+ "* -h Display help message.\n\t" + "* -s Source folder.\n\t"
				+ "* -d Destination folder - Copy. (Optional)\n\t"
				+ "* -o Output filename. (Optional)\n\t"
				+ "* -c Generate compressed file. (Optional)\n\n";
	}

	/**
	 * <pre>
	 * -h Display help message.
	 * -s Source folder.
	 * -d Destination folder - Copy. (Optional)
	 * -o Output filename. (Optional)
	 * -c Generate compressed files. (Optional)
	 * -v Display verbose output. (Optional)
	 * </pre>
	 * 
	 * -s /home/david/Documents/REU/RNA/ct_files/ -d
	 * /home/david/Documents/REU/RNA/rna_files/ -v
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		if (CommandLine.containsArg(args, "-h") >= 0) {
			output.out(helpMessage());
			output.finalizeDisplay();
			return;
		}
		int temp = CommandLine.containsArg(args, "-o");
		if (temp >= 0 && temp < args.length - 1) {
			output = new Display(args[temp + 1], args[temp + 1] + "_error.log",
					true);
		}
		temp = CommandLine.containsArg(args, "-s");
		String sourceName = null;
		if (temp >= 0 && temp < args.length - 1) {
			sourceName = args[temp + 1];
		}
		temp = CommandLine.containsArg(args, "-d");
		String destinationName = null;
		if (temp >= 0 && temp < args.length - 1) {
			destinationName = args[temp + 1];
		} else {
			destinationName = ".rna/";
		}
		boolean genCompressed = CommandLine.containsArg(args, "-c") >= 0;
		output.setVerbose(CommandLine.containsArg(args, "-v") >= 0);
		File srcFile = new File(sourceName);
		processDir(srcFile, destinationName);
		if (genCompressed)
			compressFiles(srcFile, srcFile.getAbsolutePath() + ".rnas");
		output.out("\n\n\n\t[EXITING StructureAggregator.main]");
		output.finalizeDisplay();
	}
}
